import {iReactivityApi, iVisualDataItemRenderer, iVisualDataListFakeRenderer, iVisualDataListRenderer, iVisualPageData, RenderNode} from "../../packages/utils/types.base";
import {predefineComponentRender} from "../../pages/public/predefineComponent.render";
import {createClasses} from "../../packages/utils/createClass";
import {createVisualEditorActionRender, createVisualEditorComponentRender} from "../../packages";
import {getBaseContainerAttrs} from "../../packages/utils/getBaseContainerAttrs";
import {getCurrentPage} from "../../packages/utils/getCurrentPage";
import {getEditorContentAttrs} from "../../packages/utils/getEditorContentAttrs";
import {iProcessActionRender} from "../../packages/createVisualEditorUser/createVisualEditorAction/createVisualEditorActionRender";
import {getChildrenStylesUnderPage} from "../../packages/utils/createPageGetChildrenStyles";
import {createVisualEditorBindingValue} from "../../packages/createVisualEditorUser/createVisualEditorBinding/createVisualEditorBindingValue";
import {predefineBindingValue} from "../../pages/public/predefineBindingValue";
import {createFakeListRenderer} from "../../packages/utils/createFakeListRenderer";

export function createCmsPreview({ api, processActionRender }: { api: iReactivityApi, processActionRender: iProcessActionRender }) {
  const { type, designComponent, reactive, computed, onMounted } = api;
  const classes = createClasses(type);
  return designComponent({
    props: {
      data: {},
    },
    setup(setup: any) {
      const state = reactive({
        // 服务端渲染模式下，无法得知客户端分辨率，这里默认渲染PC端内容
        clientWidth: 9999,
      });

      /*当前显示的页面*/
      const currentPage = computed((): iVisualPageData | undefined => getCurrentPage(setup.props.data.pages as any, state.clientWidth));

      /*监听窗口大小变化，横屏竖屏切换的时候响应式变化*/
      onMounted(() => {
        const onResize = () => state.clientWidth = document.body.clientWidth;
        window.addEventListener('resize', onResize);
        onResize();
      });

      const editor = {
        /*渲染组件*/
        render: createVisualEditorComponentRender(api),
        /*渲染动作*/
        action: createVisualEditorActionRender(api),
        /*绑定数据*/
        value: createVisualEditorBindingValue({ api, currentPage })
      };

      /*注册预定义组件渲染*/
      predefineComponentRender({ api, componentRender: editor.render, bindingValue: editor.value });
      /*注册预定义动作渲染*/
      processActionRender({ actionRender: editor.action });
      /*预定义绑定值定义*/
      predefineBindingValue({ bindingValue: editor.value });

      const renderItem: iVisualDataItemRenderer = (props) => {
        const data = props.bindList![props.bindIndex];
        if (!data) {
          return null;
        }
        const componentRender = editor.render.getComponentRender(data.code);
        if (!componentRender) {
          return null;
        }

        const baseContainerAttrs = getBaseContainerAttrs({
          data,
          style: props.style,
          classes,
        });

        const renderFakeList: iVisualDataListFakeRenderer = createFakeListRenderer({ value: editor.value, renderItem, currentPage });

        const renderContainer = (content?: RenderNode) => {
          if (data.action) {
            const componentAction = editor.action.getActionRender(data.action.code);
            if (!!componentAction) {
              return componentAction(data, content, baseContainerAttrs);
            }
          }
          return (
            <div {...baseContainerAttrs}>{content}</div>
          );
        };

        const componentRenderContent = componentRender({ data, page: currentPage.value!, renderItem, renderList, renderFakeList, isPreview: true, getBindingValue: editor.value.getBindingValue });

        if (typeof componentRenderContent === "function") {
          /*自定义包裹节点*/
          return componentRenderContent(renderContainer());
        } else {
          /*默认包裹节点*/
          return renderContainer(componentRenderContent);
        }
      };

      const renderList: iVisualDataListRenderer = (props) => {
        return props.scope.childrenData?.map((item, index) => {
          return renderItem({
            bindList: props.scope.childrenData!,
            bindIndex: index,
            style: !props.getChildrenStyles ? undefined : props.getChildrenStyles({ data: item, index: index, page: currentPage.value! })
          });
        });
      };

      return () => {
        const contentAttrs = getEditorContentAttrs({ classes, page: currentPage.value, isPreview: true });
        return (
          <div {...contentAttrs}>
            {currentPage.value?.childrenData.map((_, index) => renderItem({
              bindList: currentPage.value?.childrenData,
              bindIndex: index,
              style: getChildrenStylesUnderPage({ page: currentPage.value!, index })
            }))}
          </div>
        );
      };
    },
  });
}
